package com.qianfeng.chinatelcom.apigateway.filters;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qianfeng.chinatelcom.apigateway.feign.CacheService;
import com.sun.org.apache.xml.internal.security.Init;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Created by Jackiechan on 2021/12/2/下午2:14
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Component
public class IdentityFilter extends ZuulFilter {

    private CacheService cacheService;

    private LoadingCache loadingCache;

    @PostConstruct
    public void init() {
        loadingCache= CacheBuilder.newBuilder().expireAfterWrite(60, TimeUnit.SECONDS).build(new CacheLoader<String, Boolean>() {
            @Override
            public Boolean load(String s) throws Exception {
                //如果缓存中没有数据，从什么地方加载数据
                Boolean suibianxie = cacheService.setNx(s, "suibianxie", 120);
                return suibianxie;
            }
        });
    }


    @Autowired
    public void setCacheService(CacheService cacheService) {
        this.cacheService = cacheService;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER+13;
    }

    @Override
    public boolean shouldFilter() {
//        RequestContext context = RequestContext.getCurrentContext();
//        return context.sendZuulResponse();
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        //获取到签名，然后去redis中查询存在与否就可以了
        //如果存在， 就代表已经发送过，如果不存在就代表没发送过
        //not exist
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String sign = request.getParameter("sign");
        //每次都查询缓存好像有点太麻烦，万一上一次请求也是经过了当前服务器呢？我们用redis 的主要原因是担心我们的服务器是集群，第一次用户访问a服务器，这次访问当前服务器，会出现数据不一致的情况
        //我们可以在本地服务器也保存一份，如果本地直接可以过滤的就直接过滤
        //我们本地用什么保存？主要是过期的问题，因为不能无限期的保存
       //我们前面有时间戳的校验，所以超出一分钟的请求都不会到达当前过滤器，所以我们的数据大部分情况下设置60秒就够了，此处设置120是避免出现未来一分钟的请求过来了，它的有效期就是2分钟
      // Boolean suibianxie = cacheService.setNx(sgin, "suibianxie", 120);
        Boolean o = false;
        try {
            o = (Boolean) loadingCache.get(sign);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        if (!o) {
            //设置失败，因为这个数据已经存在于redis中，所以就是重复请求
            context.setSendZuulResponse(false);
            context.setResponseBody("请勿重复提交请求");
            context.addZuulResponseHeader("content-Type","text/html;charset=utf-8");
        }else{
            loadingCache.put(sign,false);//改成false 的原因是因为我们第一次是允许通过的，第二次就应该改成false不允许通过
        }
        return null;
    }
}
